﻿using System;
using System.Windows.Input;

namespace ApiScannerShell
{
    internal class DelegateCommand: ICommand
    {
        private readonly Action _ExecuteHandler;
        private readonly Func<bool> _CanExcuteHandler;

        public DelegateCommand(Func<bool> canExcuteHandler, Action executeHandler)
        {
            if (canExcuteHandler == null) throw new ArgumentNullException("canExcuteHandler");
            if (executeHandler == null) throw new ArgumentNullException("executeHandler");
            _CanExcuteHandler = canExcuteHandler;
            _ExecuteHandler = executeHandler;
        }

        public DelegateCommand(Action executeHandler): this(() => true, executeHandler)
        {
        }

        public void Execute(object parameter)
        {
            _ExecuteHandler();
        }

        public bool CanExecute(object parameter)
        {
            return _CanExcuteHandler();
        }

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_CanExcuteHandler != null)
                {
                    CommandManager.RequerySuggested += value;
                }
            }
            remove
            {
                if (_CanExcuteHandler != null)
                {
                    CommandManager.RequerySuggested += value;
                }
            }
        }
    }

    internal sealed class DelegateCommand<T> : ICommand
    {
        private readonly Action<T> _ExecuteHandler;
        private readonly Func<T, bool> _CanExcuteHandler;

        public DelegateCommand(Func<T, bool> canExcuteHandler, Action<T> executeHandler)
        {
            if (canExcuteHandler == null) throw new ArgumentNullException("canExcuteHandler");
            if (executeHandler == null) throw new ArgumentNullException("executeHandler");
            _CanExcuteHandler = canExcuteHandler;
            _ExecuteHandler = executeHandler;
        }

        public DelegateCommand(Action<T> executeHandler): this(o => true, executeHandler)
        {
        }

        public void Execute(object parameter)
        {
            _ExecuteHandler((T) parameter);
        }

        public bool CanExecute(object parameter)
        {
            return _CanExcuteHandler((T)parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_CanExcuteHandler != null)
                {
                    CommandManager.RequerySuggested += value;
                }
            }
            remove
            {
                if (_CanExcuteHandler != null)
                {
                    CommandManager.RequerySuggested += value;
                }
            }
        }
    }
}